﻿
using System.Collections.Generic;

namespace Math2DStruct
{
    public struct Circle
    {
        public XVector2 center;
        public XNumber radius;

        public Circle(XVector2 center, XNumber radius)
        {
            this.center = center;
            this.radius = radius;
        }

        public bool CheckIn(XVector2 point)
        {
            var distance = (point - center).magnitude;
            return distance < radius;
        }



        public PointWithLineSegmentResult PointWithLineSegment(XVector2 linePointOne, XVector2 linePointTwo)
        {
            var result = new PointWithLineSegmentResult()
            {
                reason = 0x00,
                points = new List<XVector2>()
            };

            var pointOneIn = CheckIn(linePointOne);
            var pointTwoIn = CheckIn(linePointTwo);

            if (pointOneIn && pointTwoIn)
            {
                result.reason = 0x02;
                return result;
            }

            // 圆心到线段直线的垂点
            var lineDir = (linePointOne - linePointTwo).normalized;
            var hDis = XVector2.Dot((center - linePointOne), lineDir);
            var vPoint = linePointOne + lineDir * hDis;
            var vDis = (center - vPoint).magnitude;
            if (vDis > radius)
            {
                result.reason = 0x01;
                return result;
            }

            // 垂点不在线段上
            if (!pointOneIn && !pointTwoIn)
            {
                if (XVector2.Dot(linePointOne - vPoint, linePointTwo - vPoint) > 0)
                {
                    result.reason = 0x01;
                    return result;
                }
            }

            // 垂点在圆上
            var lineDis = (linePointOne - linePointTwo).magnitude;
            if (vDis == radius)
            {
                if (hDis < 0 || hDis > lineDis)
                {
                    result.reason = 0x01;
                    return result;
                }

                if (hDis == 0)
                {
                    result.points.Add(linePointOne);
                    return result;
                }

                if (hDis == lineDis)
                {
                    result.points.Add(linePointTwo);
                    return result;
                }

                result.points.Add(vPoint);
                return result;
            }

            var hDis2 = XIntMath.Sqrt(radius * radius - vDis * vDis);

            // 一个交点
            if (pointOneIn)
            {
                var cPoint = vPoint - lineDir * hDis2;
                result.points.Add(cPoint);
                return result;
            }

            if (pointTwoIn)
            {
                var cPoint = vPoint + lineDir * hDis2;
                result.points.Add(cPoint);
                return result;
            }

            // 两个交点
            var tPoint = lineDir * hDis2;
            result.points.Add(vPoint + tPoint);
            result.points.Add(vPoint - tPoint);
            return result;
        }

        public struct PointWithLineSegmentResult
        {
            // 0x00: default value
            // 0x01: zero cross-point, lineSegment is out of this circle
            // 0x02: zero cross-point, lineSegment is int this circle
            public byte reason;
            public List<XVector2> points;
        }
    }
}
